package com.llh.demo4tree.service

import com.llh.demo4tree.entity.NodeAddVO
import com.llh.demo4tree.entity.ResponseVO
import com.llh.demo4tree.entity.TreeNodeMoveVO
import com.llh.demo4tree.entity.TreeVO
import com.llh.demo4tree.model.TreeNode
import com.llh.demo4tree.model.TreeNodes
import com.llh.demo4tree.util.NodePathUtil
import org.ktorm.database.Database
import org.ktorm.dsl.batchUpdate
import org.ktorm.dsl.eq
import org.ktorm.dsl.like
import org.ktorm.dsl.update
import org.ktorm.entity.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime
import java.util.concurrent.CopyOnWriteArrayList

/**
 *
 * Created At 2021/8/3 17:14
 * @author llh
 */
@Service
class TreeNodeService {
    @Autowired
    private lateinit var database: Database

    fun addNode(node: NodeAddVO) {
        val nodeSave = TreeNode {
            name = node.name
            nodePath = node.nodePath
            pId = node.pId
            createTime = LocalDateTime.now()
        }
        database.sequenceOf(TreeNodes).add(nodeSave)
    }

    /**
     * 查询指定节点开始的树形结构。
     * [nodeId]为空时则查询所有
     */
    fun findSubTree(nodeId: Int? = null): TreeVO? {
        if (nodeId != null) {
            val nodeInDB = database.sequenceOf(TreeNodes).find { it.id eq nodeId } ?: return null
            val dataList = database.sequenceOf(TreeNodes).filter {
                it.nodePath like NodePathUtil.contact(nodeInDB.nodePath, nodeInDB.id) + "%"
            }.toList()
            return NodePathUtil.assembleTreeData(dataList, nodeInDB)
        }
        val dataList = database.sequenceOf(TreeNodes).toList()
        return NodePathUtil.assembleTreeData(dataList)
    }


    @Transactional
    fun moveNode(moveVO: TreeNodeMoveVO): ResponseVO {
        val dataList = database.sequenceOf(TreeNodes).toList()
        val sourceNode = dataList.firstOrNull {
            it.id == moveVO.sourceId
        } ?: return ResponseVO(false, "被移动节点不存在！")

        val targetNode = dataList.firstOrNull {
            it.id == moveVO.targetId
        }

        val orderNum = if (targetNode == null) {
            NodePathUtil.computeOrderNum(dataList)
        } else {
            NodePathUtil.computeOrderNum(targetNode, moveVO.direction, dataList)
        }
        sourceNode.orderNum = orderNum
        sourceNode.pId = moveVO.sourcePid
        sourceNode.nodePath = NodePathUtil.nodePathTraverse(sourceNode, dataList)

        val needModifyNode = CopyOnWriteArrayList<TreeNode>()
        dataList.parallelStream()
            // 被移动节点已在列表中，过滤掉
            .filter { it.id != sourceNode.id }
            .forEach {
                val path = NodePathUtil.nodePathTraverse(it, dataList)
                if (path != it.nodePath) {
                    it.nodePath = path
                    needModifyNode.add(it)
                }
            }

        database.batchUpdate(TreeNodes) {
            needModifyNode.forEach { ele ->
                item {
                    set(it.nodePath, ele.nodePath)
                    where { it.id eq ele.id }
                }
            }
        }
        database.update(TreeNodes) {
            set(it.nodePath, sourceNode.nodePath)
            set(it.pId, sourceNode.pId)
            set(it.orderNum, sourceNode.orderNum)
            where { it.id eq sourceNode.id }
        }
        return ResponseVO()
    }


}